/***************************************************************************
 *   oboe.core.Oboe														   *
 *   Copyright (C) 2011 by Felipe Manga									   *
 *   lufeboma@gmail.com													   *
 *									 									   *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the	   *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to	   *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:						 					   *
 *									 									   *
 *   The above copyright notice and this permission notice shall be		   *
 *   included in all copies or substantial portions of the Software.	   *
 *									 									   *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,	   *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF	   *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR	   *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.					                   *
 ***************************************************************************/

package oboe.core;

#if flash
import flash.display.DisplayObject;
import flash.Lib;
import flash.events.Event;
#else
import haxe.Timer;
import oboe.controllers.StateMachine;
#end

import oboe.core.ISigSlot;

class Oboe
{
	public static var flags:Dynamic;
	public static var root:ISigSlot;
	public static var global:SigSlotCollection;
	
	#if flash
	private static var _baseTime : Float;
	private static var lastFPSTraceTime : Float;
	private static var frameCount : Int;
	private static var previousFPS : Int;
	#end
	

	public static function initOboe( flags:Dynamic, rootClass:Class<Dynamic> ):Void
	{
		global = new SigSlotCollection();
		
		Oboe.flags = flags;
		var root:Dynamic = Type.createInstance( rootClass, [] );
		
		#if flash
		if ( Std.is( root, DisplayObject ) )
		{
			flash.Lib.current.addChild( root );
		}
		previousFPS = -1;
		
		Lib.current.addEventListener( Event.ENTER_FRAME, onEnterFrame );
		Lib.current.addEventListener( Event.ADDED_TO_STAGE, onAddToStage );
		#else
			global.addChild( new OboeGlobalCollection() );
		#end
		
		if ( Std.is( root, ISigSlot ) )
		{
			Oboe.root = root;
		}
		
		var ss:SigSlot = Reflect.field( root, "sigslot" );
		ss.message("__setRootedSigSlot", [true] );
		ss.message( "onAddToParent", [] );
	}
	
	#if flash
	
	private static function onAddToStage( e:Event ):Void
	{
		Lib.current.removeEventListener( Event.ADDED_TO_STAGE, onAddToStage );
		Lib.current.stage.addEventListener( Event.RESIZE, onResizeStage );
	}
	
	private static function onResizeStage( e:Event ):Void
	{
		global.signalDown( "onStageResize", [Lib.current.stage.stageWidth, Lib.current.stage.stageHeight] );
	}
	

	private static function onEnterFrame( e:Event ):Void
	{
		var now : Float = haxe.Timer.stamp();
		var time : Float = (now - _baseTime);
		_baseTime = now;
		/* quick and buggy * /
		global.signalDown( "onPreTick", [time] );
		global.signalDown( "onTick", [time] );
		global.signalDown( "onPostTick", [time] );
		/*/ // slow and stable
		root.sigslot.shortSignal( "onPreTick", [time] );
		root.sigslot.signal( "onTick", [time] );
		root.sigslot.shortSignal( "onPostTick", [time] );
		/* */
		
		if( Oboe.flags.TRACE_FPS )
		{
			frameCount++;
			time = (now - lastFPSTraceTime); 
			if( time > 10 )
			{
				lastFPSTraceTime = now;
				now = Math.round(frameCount/time);
				if( now != previousFPS )
				{
					haxe.Log.trace( "FPS: " + now );
					previousFPS = Math.round(now);
				}
				frameCount = 0;
			}
		}
	}
	
	#end
}

#if !flash
class OboeGlobalCollection extends SigSlot
{
	public function new()
	{
		super();
	}
	
	@slot function onSetState( stateMachine:StateMachine ):Void
	{
		#if !php
		Timer.delay( 
			function() { 
				stateMachine.forceStateUpdate(); 
			}, 1 );
		#else
		stateMachine.forceStateUpdate();
		#end
	}
}
#end
